package com.octopus.yangj.customized.controller;

import java.util.HashSet;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.octopus.yangj.generated.model.EmployeeRoleStruct;
import com.octopus.yangj.generated.model.EmployeeStruct;
import com.octopus.yangj.customized.model.CustomizedEmployeeRoleStruct;
import com.octopus.yangj.customized.service.LogService;
import com.octopus.yangj.customized.service.RealmService;
import com.octopus.yangj.generated.service.EmployeeService;

/**
 * Web controller used when loading the home page.
 */
@Controller
@RequestMapping("/common")
public class CommonController {
	
	private static Log log = LogFactory.getLog(CommonController.class);
	
	@Autowired
    private LoginValidator loginValidator;
    
	@Autowired
    private SignupValidator userValidator;

    @Autowired
    private EmployeeService userService;
    
    @Autowired
    private RealmService realmService;
    
    @Autowired
    private LogService logService;

    @RequestMapping("/home.o")
    public String viewHome(Model model, @ModelAttribute LoginCommand command ) {
    	this.realmService.getCurrentUser();
    	return "common/home";
    }
    
    @RequestMapping("/mainright.o")
    public String viewMainRight(Model model, @ModelAttribute LoginCommand command ) {
    	return "common/mainright";
    }
    
    @RequestMapping("/mainleft.o")
    public String viewMainLeft(Model model, @ModelAttribute LoginCommand command ) {
    	return "common/mainleft";
    }
    
    @RequestMapping("/maincenter.o")
    public String viewMainCenter(Model model, @ModelAttribute LoginCommand command ) {
    	return "common/maincenter";
    }
    
    @RequestMapping("/maintop.o")
    public String viewMainTop(Model model, @ModelAttribute LoginCommand command ) {
    	return "common/maintop";
    }
    
    @RequestMapping("/maindown.o")
    public String viewMainDown(Model model, @ModelAttribute LoginCommand command ) {
    	return "common/maindown";
    }

    @RequestMapping(value="/login.o",method= RequestMethod.GET)
    public String showLoginForm(Model model, @ModelAttribute LoginCommand command ) {
    	final Long currentUserId = (Long) SecurityUtils.getSubject().getPrincipal();
    	if(currentUserId != null)
    		return "redirect:/common/home.o";
        return "common/login";
    }

    @RequestMapping(value="/login.o",method= RequestMethod.POST)
    public String login(Model model, HttpServletRequest request, @ModelAttribute LoginCommand command, BindingResult errors) {
    	loginValidator.validate(command, errors);
        if( errors.hasErrors() ) {
            return showLoginForm(model, command);
        }
        UsernamePasswordToken token = new UsernamePasswordToken(command.getUsername(), command.getPassword(), command.isRememberMe());
        try {
            SecurityUtils.getSubject().login(token);
        } catch (AuthenticationException e) {
        	log.error("Invalid username or password.");
            errors.reject( "error.login.invalid", "Invalid username or password.  Please try again." );
        }
        if( errors.hasErrors() ) {
            return showLoginForm(model, command);
        } else {
        	this.realmService.getCurrentUser();
            return "redirect:/common/home.o";
        }
    }

    @RequestMapping("/logout.o")
    public String logout() {
        SecurityUtils.getSubject().logout();
        SecurityUtils.getSubject().getSession().removeAttribute("currentUser");
        return "redirect:/";
    }
    
    @RequestMapping(value="/signup.o",method= RequestMethod.GET)
    public String showSignupForm(Model model, @ModelAttribute EmployeeStruct user) {
        return "common/signup";
    }

    @RequestMapping(value="/signup.o",method= RequestMethod.POST)
    public String showSignupForm(Model model, @ModelAttribute EmployeeStruct user, BindingResult errors) {
    	userValidator.validate(user, errors);
        if( errors.hasErrors() ) {
            return showSignupForm(model, user);
        }
        String password = user.getPassword();
        user.setPassword(new Sha256Hash(password).toHex());
        if(user.getRoles() == null || user.getRoles().size() == 0){
	    	EmployeeRoleStruct role = new EmployeeRoleStruct();
	    	role.setId(new Long(CustomizedEmployeeRoleStruct.ROLE_USER));
	    	Set<EmployeeRoleStruct> roles = new HashSet<EmployeeRoleStruct>();
	    	roles.add(role);
	    	user.setRoles(roles);
        }
        try{
        	userService.createEntity(user);
        	logService.log("user", "sign", null);
        } catch (DataIntegrityViolationException _x) {
            _x.printStackTrace();
            errors.rejectValue("id", "error.common.model.exist", "The entity has already existed.");
            return showSignupForm(model, user);
        }
        SecurityUtils.getSubject().login(new UsernamePasswordToken(user.getUsername(), password));
        return "redirect:/user/x/profile.o";
    }
    
    @RequestMapping("/unauthorized.o")
    public void unauthorized(Model model) {
    	EmployeeStruct user =  this.realmService.getCurrentUser();
    	model.addAttribute("currentUser", user);
    }

}
